/*
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *
 *   版权所有  2014-2015 成都星锐蓝海网络科技有限公司
 *   商业许可请联系  +86-18682011860    QQ:66442834
 *   
 */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include "xyz_log.h"
#include "wmpctrl.h"
#include "udphelp.h"
#include "wtpinfo.h"
#include "wtpnl.h"

#include "global.h"


struct join_rep {
	uint32_t rescode;
	uint32_t echo;
	uint32_t imgup;
	struct img_ident img;
};

static int S_portal_flag = 0;

extern int G_wmpsock;
extern struct sockaddr_in G_wmpaddr;

static int joinParseRep(WMMSG *msg, struct join_rep *rep);
static int joinHandleRep(struct join_rep *rep);
extern int nsap_firm_upgr_thread(void);
extern const char *wtpInfoGetBoardName(void);

void wmpJoin(int *state)
{
	WMMSG reqmsg;
	WMMSG repmsg;
	BUFF attr;
	struct sockaddr_in from;
	int len = 0;
	uint16_t seqnum = 0;
	uint8_t *apid = NULL;
	struct join_rep rep;
	uint8_t *p = NULL;

	if (G_wmpsock > 0) {
		udpCloseConnect(G_wmpsock);
	}
	G_wmpsock = udpNewNonblockLongConnect(NULL, NULL, wtpinfoGetACIPStr(), WMP_CTRL_PORT_STR);
	if (G_wmpsock < 0) {
		xyz_log_error("New UDP long connect error");
		*state = WTP_STATE_SULK;
		return;
	}

//	apid = (uint8_t *)nsap_deid_get_byte();
                apid = (uint8_t *)devid;
                
	seqnum = wtpInfoGetSEQNUM();
	if (wmmClearInit(&reqmsg, apid, seqnum, WMM_CODE_JOIN_REQ)) {
		xyz_log_error("Message head INIT error");
		*state = WTP_STATE_SULK;
		return;
	}
	nsap_firm_ver_t *ver = (nsap_firm_ver_t *)nsap_firm_version();
	wmmPackBoard(&attr, ver->major, ver->minor, ver->patch, wtpInfoGetBoardName());
	if (wmmPutAttrBuff(&reqmsg, &attr)) {
		xyz_log_error("Put attribute error");
		*state = WTP_STATE_SULK;
		return;
	}
	if (udpSend(G_wmpsock, reqmsg.buff, reqmsg.offset, &G_wmpaddr) < 1) {
		xyz_log_error("sendto : %s", strerror(errno));
		*state = WTP_STATE_SULK;
		return;
	}
        
        xyz_log_debug("apid is %s",apid);
	len = udpTimeRecv(G_wmpsock, repmsg.buff, WMM_BUFF_SIZE, &from, 2000);
	if (len < 1) {
		xyz_log_error("RECV message error");
		*state = WTP_STATE_SULK;
		return;
	}
	if (from.sin_addr.s_addr != G_wmpaddr.sin_addr.s_addr) {
		xyz_log_error("Message source error");
		*state = WTP_STATE_SULK;
	}
	repmsg.totlen = len;
	if (wmmPrepRecvd(&repmsg)) {
		xyz_log_error("Preprocess message error");
		*state = WTP_STATE_SULK;
		return;
	}
	if (repmsg.seqnum != seqnum) {
		xyz_log_error("Response message SEQ-NUM %d don't match %d", repmsg.seqnum, seqnum);
		*state = WTP_STATE_SULK;
		return;
	}
	if (WMM_CODE_JOIN_REP == repmsg.code) {
		memset(&rep, 0, sizeof(rep));
		if (joinParseRep(&repmsg, &rep)) {
			xyz_log_error("Parse response message error");
			*state = WTP_STATE_SULK;
			return;
		}
		if (joinHandleRep(&rep)) {
			xyz_log_error("Handle response message error");
			*state = WTP_STATE_SULK;
			return;
		}
		if (1 == rep.imgup) {
			/*  开启线程下载固件    */
//			*state = WTP_STATE_IMAGE;
			nsap_firm_upgr_thread();
		}
		*state = WTP_STATE_RUN;
	}
}


static int joinParseRep(WMMSG *msg, struct join_rep *rep)
{
	int rc = 0;
	BUFF attr;
/*
	if (nsap_wifi_uci_zero_file()) {
		xyz_log_error("empty wireless failed");
		return -1;
	}
       */
	S_portal_flag = 0;
	for ( ; ; ) {
		memset(&attr, 0, sizeof(attr));
		rc = wmmGetAttr(msg, &attr);
		if (1 == rc) {
			switch (attr.type) {
                            
			case WMM_ATTR_RESCODE :
				if (wmmParseResCode(&attr, &(rep->rescode))) {
					xyz_log_error("Parse Result-Code error");
					return -1;
				}
				break;
			case WMM_ATTR_ECHO:
				if (wmmParseEcho(&attr, &(rep->echo))) {
					xyz_log_error("Parse ECHO-TIME error");
					return -1;
				}
				break;
			case WMM_ATTR_IDLE:
				if (wtpnlmsgHandleIdle(&attr)) {
					xyz_log_error("Parse handle IDLE-TIME error");
					return -1;
				}
				break;
			case WMM_ATTR_WIFICFG:
				if (wtpnlmsgHandleWiFi(&attr)) {
					xyz_log_error("Parse handle WiFi-CFG error");
					return -1;
				}
				break;
			case WMM_ATTR_PRTCFG:
				if (wtpnlmsgHandlePortal(&attr)) {
					xyz_log_error("Parse handle PORTAL-CFG error");
					return -1;
				}
				S_portal_flag = 1;
				break;
			case WMM_ATTR_FREEIP:
				if (wtpnlmsgHandleFreeIP(&attr)) {
					xyz_log_error("Parse handle FREE-IP error");
					return -1;
				}
				break;
			case WMM_ATTR_IMGID:
				wmmParseImageIdent(&attr, &(rep->img));
				rep->imgup = 1;
				break;
			case WMM_ATTR_ACCT:
				if (wtpnlmsgHandleAcct(&attr)) {
					xyz_log_error("Parse handle ACCT-TIME error");
					return -1;
				}
				break;
			case WMM_ATTR_FREEURL :
				if (wtpnlmsgHandleFreeURL(&attr)) {
					xyz_log_error("Parse handle FREE-URL error");
					return -1;
				}
				break;
			case WMM_ATTR_ORG :
				if (wtpnlmsgHandleOrg(&attr)) {
					xyz_log_error("Parse Org-Id error");
					return -1;
				}
				break;
			case WMM_ATTR_BRC :
				if (wtpnlmsgHandleBrc(&attr)) {
					xyz_log_error("Parse Brc-Id error");
					return -1;
				}
				break;
			default:
				xyz_log_error("Unknown message attribute type %u, length %u", attr.type, attr.len);
				break;
			}
                       
                    sleep(1);
		} else {
			if (0 == rc) {
				break;
			} else {
				xyz_log_error("Get attribute error");
			}
		}
	}
	if (msg->offset != msg->totlen) {
		xyz_log_error("JOIN-REQ message exist unknown attribute length %d", (msg->totlen - msg->offset));
	}
	if (rep->rescode != WMM_RESULT_CODE_OK) {
		xyz_log_error("Join failed");
		rc = -1;
	}
	return rc;
}

extern int nsap_firm_set_sessid(unsigned char *id, unsigned char len);

extern u_int32_t G_net_mode;

static int joinHandleRep(struct join_rep *rep)
{
	if (1 == rep->imgup) {
		xyz_log_warn("This WTP will IMAGE UPPER");
		nsap_firm_set_sessid(rep->img.sessid, 16);
		return 0;
	}
	wtpInfoSetEcho(rep->echo);
        /*
	if (nsap_wifi_restart()) {
		xyz_log_error("Open WiFi error");
		return -1;
	}
	system("/sbin/ns_led.sh running &");
        */
        xyz_log_error("Wifi is starting...");
        /*
	if (S_portal_flag) {
		if (wtpInfoSendHookOpen2Krn(G_net_mode, "wlan0")) {
			xyz_log_error("Start HOOK error");
			return -1;
		}
	}
         * 
         */
	return 0;
}
